import uuid

from django.contrib.auth.hashers import make_password, check_password
from django.core.cache import cache
from rest_framework import serializers

from users.models import UserModel

# ModelSerializer: 实现校验字段和序列化字段的作用
# Serializer: 实现校验字段
from utils.errors import ParamsException


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        # 序列化的模型
        model = UserModel
        #  序列化的字段
        # fields = '__all__'
        fields = ['username', 'email', 'sex']

    def to_representation(self, instance):
        # 序列化每一个对象时，将主动调用的方法
        # instance参数为被序列化的对象
        data = super().to_representation(instance)
        data['u_username'] = data['username']
        del data['username']
        return data




class RegisterSerializer(serializers.Serializer):
    # 注册参数序列化
    u_username = serializers.CharField(max_length=10, min_length=3,
                                       required=True,
                                       error_messages={
                                           'required': '账号必填',
                                           'max_length': '账号不能超过10字符',
                                           'min_length': '账号不能短于3字符'
                                       })
    u_password = serializers.CharField(max_length=10, min_length=5,
                                       required=True,
                                       error_messages={
                                           'required': '账号必填',
                                           'max_length': '账号不能超过10字符',
                                           'min_length': '账号不能短于5字符'
                                       }
                                       )
    u_password2 = serializers.CharField(max_length=10, min_length=5,
                                       required=True,
                                        error_messages={
                                            'required': '账号必填',
                                            'max_length': '账号不能超过10字符',
                                            'min_length': '账号不能短于5字符'
                                        }
                                        )
    u_email = serializers.EmailField(required=True,
                                    error_messages={
                                        'required': '邮箱必填',
                                        'invalid': '请输入正确的邮箱地址'
                                    })

    def validate(self, attrs):
        # 校验账号字段是否已存在
        username = attrs.get('u_username')
        user = UserModel.objects.filter(username=username).first()
        if user:
            # 账号已存在，不能创建
            raise ParamsException({'code': 1001, 'msg': '账号已存在'})
        # 判断密码是否一致
        pw1 = attrs.get('u_password')
        pw2 = attrs.get('u_password2')
        if pw1 != pw2:
            raise ParamsException({'code': 1002, 'msg': '密码不正确'})
        # TODO: 邮箱判断是都存在
        return attrs

    def create(self, validated_data: object) -> object:
        # 调用serialzier.save()方法时，被主动调用的create方法
        username = validated_data.get('u_username')
        # 加密和解密
        password = make_password(validated_data.get('u_password'))
        # check_password('明文', '已保存的编码后的密码值')
        email = validated_data.get('u_email')
        user = UserModel.objects.create(username=username,
                                        password=password,
                                        email=email)
        return user


class LoginSerialzier(serializers.Serializer):
    u_username = serializers.CharField(max_length=10, min_length=3,
                                       required=True,
                                       error_messages={
                                           'required': '账号必填',
                                           'max_length': '账号不能超过10字符',
                                           'min_length': '账号不能短于3字符'
                                       })
    u_password = serializers.CharField(max_length=10, min_length=5,
                                       required=True,
                                       error_messages={
                                           'required': '账号必填',
                                           'max_length': '账号不能超过10字符',
                                           'min_length': '账号不能短于5字符'
                                       }
                                       )

    def validate(self, attrs):
        # 登录账号必须存在
        username = attrs.get('u_username')
        user = UserModel.objects.filter(username=username).first()
        if not user:
            raise ParamsException({'code': 1003, 'msg': '登录账号不存在，请去注册'})
        # 登录密码必须正确
        password = attrs.get('u_password')
        if not check_password(password, user.password):
            raise ParamsException({'code': 1004, 'msg': '账号或密码错误'})
        return attrs

    def login_user(self, validate_data):
        username = validate_data.get('u_username')
        user = UserModel.objects.filter(username=username).first()
        # 登录操作，使用redis进行登录标识token参数的存储
        # token是后端返回给前端的登录标识符
        token = uuid.uuid4().hex
        # redis中以字符串格式存储数据，key为token，value为用户id值
        cache.set(token, user.id, timeout=86400)
        return token
